<!--  -->
<template>
  <div>
    <el-switch
      v-model="draggable"
      active-text="开启拖拽"
      inactive-text="关闭拖拽">
    </el-switch>
    <el-button type="primary"
      @click="batchUpdate">
      保存</el-button>
    <el-button type="danger"
      @click="batchDelete">
      批量删除
    </el-button>
    <el-tree :data="menus"
      :props="defaultProps"
      @node-click="handleNodeClick"
      :expand-on-click-node="false"
      show-checkbox
      node-key="catId"
      :default-expanded-keys="expandedKey"
      :draggable="draggable"
      :allow-drop="allowDrop"
      @node-drop="handleDrop"
      ref="menuTree">
      <span
        class="custom-tree-node"
        slot-scope="{ node, data }">
        <span>{{ node.label }}</span>
        <span>
          <!-- node.level 小于等于2说明是一级或者是二级菜单 -->
          <el-button
            type="text"
            size="mini"
            v-if="node.level <= 2"
            @click="() => append(data)">
            添加
          </el-button>
          <el-button
            type="text"
            size="mini"
            v-if="node.childNodes.length == 0"
            @click="() => remove(node, data)">
            删除
          </el-button>
          <el-button
            type="text"
            size="mini"
            @click="() => update(data)">
            修改
          </el-button>

        </span>

      </span>

    </el-tree>

    <el-dialog
      :title="dialogTitle"
      :visible.sync="dialogVisible"
      width="30%"
      :close-on-click-modal="false">
      <el-form
        :model="category">
        <el-form-item
          label="分类名称">
          <el-input
            v-model="category.name"
            autocomplete="off">
          </el-input>
        </el-form-item>
        <el-form-item
          label="图标">
          <el-input
            v-model="category.icon"
            autocomplete="off">
          </el-input>
        </el-form-item>
        <el-form-item
          label="计量单位">
          <el-input
            v-model="category.productUnit"
            autocomplete="off">
          </el-input>
        </el-form-item>
      </el-form>
      <span slot="footer"
        class="dialog-footer">
        <el-button
          @click="dialogVisible = false">
          取 消</el-button>
        <el-button
          type="primary"
          @click="submitData()">
          确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
//这里可以导入其他文件（比如：组件，工具js，第三方插件js，json文件，图片文件等等）
//例如：import 《组件名称》 from '《组件路径》';

import { title } from 'process'

export default {
  //import引入的组件需要注入到对象中才能使用
  components: {},
  data() {
    return {
      // 当前节点的父节点id
      pCid: [],
      draggable: false, // 用于控制是否可以拖拽
      updateNodes: [], // 定义修改节点的数组
      maxLevel: 0,
      dialogTitle: '',
      dialogType: '', // 判断是新增还是修改
      category: {
        name: '',
        parentCid: 0,
        catLevel: 0,
        showStatus: 1,
        sort: 0,
        icon: '',
        productUnit: '',
      },
      dialogVisible: false,
      menus: [],
      expandedKey: [],
      defaultProps: {
        children: 'children',
        label: 'name',
      },
    }
  },
  methods: {
    batchDelete() {
      let batchDeleteIds = []
      let cheaked = this.$refs.menuTree.getCheckedNodes()
      for (let i = 0; i < cheaked.length; i++) {
        batchDeleteIds.push(cheaked[i].catId)
      }
      this.$confirm(`批量删除这些菜单, 是否继续?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => {
          this.$http({
            url: this.$http.adornUrl('/product/category/delete'),
            method: 'post',
            data: this.$http.adornData(batchDeleteIds, false),
          }).then(({ data }) => {
            this.$message({
              type: 'success',
              message: '删除成功!',
            })
            this.getMenus()
          })

          this.$message({
            type: 'success',
            message: '删除成功!',
          })
        })
        // 取消的操作，先留空，不然控制会报错
        .catch(() => {})
    },

    batchUpdate() {
      // 当前拖拽节点的最新层级
      this.$http({
        url: this.$http.adornUrl('/product/category/update/sort'),
        method: 'post',
        data: this.$http.adornData(this.updateNodes, false),
      }).then(({ data }) => {
        this.$message({
          type: 'success',
          message: '修改顺序成功!',
        })
        // 修改成功刷新菜单
        this.getMenus()
        console.log(this.pCid)
        this.expandedKey = this.pCid
        this.updateNodes = []
        this.maxLevel = 0
        this.pCid = 0
      })
    },
    handleDrop(draggingNode, dropNode, dropType) {
      console.log('tree drop: ', dropNode.label, dropType)
      // 当前节点的父节点id
      let pCid = 0
      let sillings = null // 兄弟节点
      // 以前面或者后面的方式进入
      if (dropType == 'before' || dropType == 'after') {
        pCid =
          dropNode.parent.data.catId == undefined // 防止出现undefined
            ? 0
            : dropNode.parent.data.catId
        sillings = dropNode.parent.childNodes
      } else {
        pCid = dropNode.data.catId
        sillings = dropNode.childNodes
      }
      // 当前拖拽节点的最新顺序
      for (let i = 0; i < sillings.length; i++) {
        // 如果遍历的是当前正在拖拽的节点
        if (sillings[i].data.catId == draggingNode.data.catId) {
          // 如果遍历的是当前正在拖拽的节点
          let catLevel = draggingNode.level
          // 如果当前节点的层级发生变化
          if (sillings[i].level != draggingNode.level) {
            // 修改他的子节点的层级
            catLevel = sillings[i].level
            this.updateChildNodeLevel(sillings[i])
          }
          this.updateNodes.push({ catId: sillings[i].data.catId, sort: i, parentCid: pCid })
        } else {
          this.updateNodes.push({ catId: sillings[i].data.catId, sort: i })
        }
        this.pCid.push(pCid)
      }
    },
    updateChildNodeLevel(node) {
      // 他有子节点
      if (node.childNodes.length > 0) {
        for (let i = 0; i < node.childNodes.length; i++) {
          let cNode = node.childNodes[i].data
          this.updateNodes.push({ catId: cNode.catId, catLevel: node.childNodes[i].level })
          this.updateChildNodeLevel(node.childNodes[i])
        }
      }
    },
    countNodeLevel(node) {
      // 找到所有子节点，求出最大深度
      if (node.childNodes != null || node.childNodes.length > 0) {
        // 说明有子节点
        // 有子节点就遍历
        for (let i = 0; i < node.childNodes.length; i++) {
          // 看看当前子节点的深度是否大于最大深度，如果大于就交换
          if (node.childNodes[i].level > this.maxLevel) {
            this.maxLevel = node.childNodes[i].level // 大于最大层数就递归
          }
          // 如果还有子节点的话就遍历递归调用
          this.countNodeLevel(node.childNodes[i])
        }
      }
    },
    allowDrop(draggingNode, dropNode, type) {
      // 判断是否可以拖拽的核心是当前节点以及所在父节点的总层数不可以超过3
      /// 1. 计算被拖拽的节点的总层数
      // draggingNode表示的是拖拽的节点
      this.countNodeLevel(draggingNode)
      // 计算最大深度
      let currentDepth = Math.abs(this.maxLevel - draggingNode.data.catLevel) + 1
      // 再根据拖动类型来判断计算公式
      if (type == 'inner') {
        // 如果是拖动到里面
        // 如果深度小于3，说明可以拖动
        return currentDepth + dropNode.level <= 3
      } else {
        // 如果是拖动到外面
        return currentDepth + dropNode.parent.level <= 3
      }
    },

    // 修改菜单方法
    updateCategory() {
      let { catId, name, icon, productUnit } = this.category
      let data = { catId, name, icon, productUnit }
      this.$http({
        url: this.$http.adornUrl('/product/category/update'),
        method: 'post',
        data: this.$http.adornData(data, false),
      }).then(({ data }) => {
        this.$message({
          type: 'success',
          message: '修改成功!',
        })
        // 关闭对话框
        this.dialogVisible = false
        // 会重新发送请求，更新一次菜单数据
        this.getMenus()
        // 设置需要默认展开的菜单，赋值为当前节点的父节点的id即可，当前节点的父节点为
        console.log(this.category)
        this.expandedKey = [this.category.parentCid]
      })
    },
    // 判断是修改还是新增
    submitData() {
      if (this.dialogType == 'save') {
        this.addCategory()
      }
      if (this.dialogType == 'update') {
        this.updateCategory()
      }
    },
    // 修改
    update(data) {
      this.dialogTitle = '修改分类'
      this.dialogVisible = true
      // 回显编辑框
      this.$http({
        url: this.$http.adornUrl(`/product/category/info/${data.catId}`),
        method: 'get',
      }).then(({ data }) => {
        this.category.name = data.category.name
        this.category.icon = data.category.icon
        this.category.productUnit = data.category.productUnit
        this.category.parentCid = data.category.parentCid
      })

      // 给id赋值
      this.category.catId = data.catId
      this.dialogType = 'update' // 点击编辑的时候把值修改为update
      this.dialogTitle = '修改'
    },
    // 添加三级分类的数据
    addCategory() {
      console.log(this.category)
      this.$http({
        url: this.$http.adornUrl('/product/category/save'),
        method: 'post',
        data: this.$http.adornData(this.category, false),
      }).then(({ data }) => {
        this.$message({
          type: 'success',
          message: '保存成功!',
        })
        // 关闭对话框
        this.dialogVisible = false
        this.category.name = ''
        this.category.icon = ''
        this.category.productUnit = ''
        // 会重新发送请求，更新一次菜单数据
        this.getMenus()
        // 设置需要默认展开的菜单，赋值为当前节点的父节点的id即可，当前节点的父节点为
        this.expandedKey = [this.category.parentCid]
      })
    },
    handleNodeClick(data) {
      // cxonsole.log(data)
    },
    append(data) {
      this.dialogTitle = '新增分类'
      this.dialogType = 'save'
      this.dialogVisible = true
      this.category.parentCid = data.catId
      this.category.catLevel = data.catLevel + 1

      this.category.name = ''
      this.category.icon = ''
      this.category.productUnit = ''
    },

    remove(node, data) {
      var ids = [data.catId]
      this.$confirm(`是否删除【${data.name}】菜单, 是否继续?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => {
          this.$http({
            url: this.$http.adornUrl('/product/category/delete'),
            method: 'post',
            data: this.$http.adornData(ids, false),
          }).then(({ data }) => {
            // 会重新发送请求，更新一次菜单数据
            this.getMenus()
            // 设置需要默认展开的菜单，赋值为当前节点的父节点的id即可，当前节点的父节点为
            this.expandedKey = [node.parent.data.catId]
          })

          this.$message({
            type: 'success',
            message: '删除成功!',
          })
        })
        // 取消的操作，先留空，不然控制会报错
        .catch(() => {})
    },
    getMenus() {
      this.$http({
        url: this.$http.adornUrl('/product/category/list'),
        method: 'get',
      }).then(({ data }) => {
        // console.log(data.categoryEntityList)
        this.menus = data.categoryEntityList
      })
    },
  },
  //监听属性 类似于data概念
  computed: {},
  //监控data中的数据变化
  watch: {},
  //方法集合
  //生命周期 - 创建完成（可以访问当前this实例）
  created() {
    this.getMenus()
  },
  //生命周期 - 挂载完成（可以访问DOM元素）
  mounted() {},
  beforeCreate() {}, //生命周期 - 创建之前
  beforeMount() {}, //生命周期 - 挂载之前
  beforeUpdate() {}, //生命周期 - 更新之前
  updated() {}, //生命周期 - 更新之后
  beforeDestroy() {}, //生命周期 - 销毁之前
  destroyed() {}, //生命周期 - 销毁完成
  activated() {}, //如果页面有keep-alive缓存功能，这个函数会触发
}
</script>
<style lang='scss' scoped>
//@import url(); 引入公共css类
</style>